Windows NT does not provide queues. However, several people who were used to using the DosQueue functions of OS/2 have asked for this functionality -- so here it is. In general, this implementation relies upon shrmem.dll, the shared memory handling dll I wrote earlier. I have also changed the syntax for some of these functions. I hope that the newer functions will be easier to use. Their are two main differences in the use/syntax presented here from the original. The first relates to the use of shared memory in combination with queues. An OS/2 algorithm for writing to a queue looks like this: OpenQueue() and remember queue owner PID. Allocate shared memory Turn shared memory seg into a pointer place data in shared memory Give the seg to the owner of the queue, unless I own the queue. WriteQueue, giving a pointer, length, priority, and event code. The OS/2 queue reader then: ReadQueue, getting the writer id and event code in a structure, the priority in a seperate variable, and the pointer/length in two others. Free shared memory ===================== The useage here changes slightly: An algorithm for writing to a queue looks like this: OpenQueue() Allocate shared memory Lock shared memory place data in shared memory Unlock Shared memory WriteQueue, giving a shared memory handle, priority, and event code. The queue reader then: ReadQueue, all info (see queue_elem below) provided in a structure. Lock/Use/Unlock shared memory Free shared memory The applications qsrv.exe and qclient.exe contain my test routines. ==================================================== API specs ==================================================== DWORD CreateQueue( PHQUEUE phq, int fQueueOrder, LPTSTR pszName); Create a queue. Anonymous queues not allowed. The name may begin with \queues\ for compatibility reasons, but can not contain any other '\\' characters. fQueueOrder one of {QUE_FIFO, QUE_LIFO, QUE_PRIORITY} return is 0 on success or: QUE_INVALID_NAME QUE_NO_MEMORY or some other result obtained from GetLastError() DWORD CloseQueue( HQUEUE hq); Close a queue. return is 0 on success or: QUE_INVALID_HANDLE DWORD OpenQueue(LPDWORD ppid, PHQUEUE phq, LPTSTR pszName); Open a queue named pszName. The Id of the process which created the queue is returned in ppid. return is 0 on success or: QUE_INVALID_NAME QUE_NO_MEMORY QUE_NAME_NOT_EXIST or some other result obtained from GetLastError() DWORD WriteQueue(HQUEUE hq, DWORD dwEventCode, DWORD dwShrHandle, DWORD dwPriority); Write to queue hq with dwEventCode, dwShrHandle, and dwPriority values. Note that all values are passed as is, so you could use this as a 3 DWORD message if you wished. Priority is 0 lowest, ascending upwards. return is 0 on success or: QUE_INVALID_HANDLE QUE_NO_MEMORY DWORD ReadQueue(HQUEUE hq, PQ_ELEMENT pqe, int iElement, BOOL fWait); Read element iElement. A negative iElement is treated as 0. iElement should be either 0 or the result of a PeekQueue call. if fWait is true, this call will block indefinitely on a handle to an event until something is in the queue. If you want finer control that this, use GetQueueEventHandle() to get the handle yourself. Data is returned in the Q_ELEMENT structure: typedef struct _queue_elem { DWORD dwWriterId; DWORD dwShrHandle; DWORD dwEventCode; DWORD dwPriority; } Q_ELEMENT; typedef Q_ELEMENT *PQ_ELEMENT; return is 0 on success or: QUE_ELEMENT_NOT_EXIST QUE_EMPTY QUE_INVALID_HANDLE QUE_INVALID_NAME QUE_NO_MEMORY or some other result obtained from GetLastError() HANDLE GetQueueEventHandle( HQUEUE hqueue); return is 0 on failure, or a Event queue you can wait on. The handle to the Event will be in the Signaled state (Wait's will not block ) while data is in the queue. DWORD PeekQueue(HQUEUE hq, PQ_ELEMENT pqe, int *piElement, BOOL fWait); This call doesn't remove the queue element from the queue. Further, you pass in a queue element (-1 means get first element, anything else will try to find queue element (*piElement)+1 returning same in piElement. Other than that, it is the same as ReadQueue. return is 0 on success or: QUE_ELEMENT_NOT_EXIST QUE_EMPTY QUE_INVALID_HANDLE QUE_INVALID_NAME QUE_NO_MEMORY or some other result obtained from GetLastError()